#include <iostream>
#include <string.h>
#include <fstream>
#include <vector>
#include <math.h>
#include <dirent.h>
using namespace std;
float strToFloat(string base , int dp = 0);
string nameGen(string ,int ,string);
string findTB(string ,string);
string findMHp(string ,string);
vector<string> getFlags(string);
string findInFile(string ,string ,string , string);
bool findSUSY(string,string);
string findSUSYValue(string , string);
bool isThere(string ,string ,string);
string rightFlag(string);
string floatToStr(float , int = 0);
int findNumberOfFiles(string);
int main()
{ 
    int N = findNumberOfFiles("FH/");
    vector<string> SH_flags = {"ggh XS in pb" ,"bbh XS in pb" ,"ggh XS in pb" ,"bbh XS in pb" ,"ggh XS in pb" ,"bbh XS in pb"};
    vector<string> SH_labels = {"ggh XS for H1" ,"bbh XS for H1" ,"ggh XS for H2" ,"bbh XS for H2" ,"ggh XS for H3" ,"bbh XS for H3"};
    vector<string> types ={"FH_H1" ,"FH_H2" ,"FH_H3" ,"FH_Hp" ,"SH_H1" ,"SH_H2" ,"SH_H3"};
    vector<string> Types ={"FH" ,"FH" ,"FH" ,"FH" ,"SH" ,"SH" ,"SH"};
    vector<string> paths = {"FH/FH_" ,"SH_H1/SH_H1_" ,"SH_H2/SH_H2_" ,"SH_H3/SH_H3_"};
    vector<string> flags[types.size()];
    string path;
    int counter = 0;
    for(int i = 0 ; i < types.size() ; i++)
    {
        if(i < 4)
            flags[i] = getFlags(types[i]);
        else
        {
            flags[i].push_back(SH_flags[(i-4)*2]);
            flags[i].push_back(SH_flags[(i-4)*2+1]);
        }
    }
    int total = 0;
    for(int i = 0 ; i < types.size() ; i++)
    {
        total += flags[i].size();
    }
    //TH2F* h2[total];
    //TFile file("2D_CPV_13.root","RECREATE");
    ofstream file("Data.txt");
    for(int i = 0 ; i < types.size() ; i++)
    {
        for(int j = 0 ; j < flags[i].size() ; j++)
        {
            vector<float> tb;
            vector<float> mhp;
            vector<float> value;
            for(int k = 0 ; k < N ; k++)
            {
                if(i < 4)
                    path = nameGen(paths[0] , k + 1 , ".fh-001");
                else
                    path = nameGen(paths[i-3] , k + 1 , ".out");
                if(isThere(path , flags[i][j] , types[i]) == true)
                {
                    if(i < 4)
                    {
                        tb.push_back(strToFloat(findTB(path , "TB")));
                    }
                    else
                        tb.push_back(strToFloat(findTB(path , "tan(beta)")));
                    mhp.push_back(strToFloat(findTB(path , "MHp")));
                    value.push_back(strToFloat(findInFile(path , flags[i][j] , Types[i] , types[i])));
                }
            }
            if(i < 4)
                file<<rightFlag(flags[i][j])<<endl;
            else
                file<<SH_labels[(i-4)*2+j]<<endl;
            for(int k = 0 ; k < tb.size() ; k++)
                file<<tb[k]<<","<<mhp[k]<<","<<value[k]<<endl;
            file<<"END\n";
            /*if(tb.size() > 0)
            {
                int tb_min = 0;
                int mhp_min = (int)(*min_element(mhp.begin() , mhp.end())) - 100;
                int tb_max = (int)(*max_element(tb.begin() , tb.end())) + 2;
                int mhp_max = (int)(*max_element(mhp.begin() , mhp.end())) + 100;
                h2[counter] = new TH2F((rightFlag(flags[i][j])).c_str(),";M_{H^{+} };tan_{#beta}",(mhp_max - mhp_min + 1) * 5 + 1,mhp_min,mhp_max,(tb_max - tb_min + 1) * 20 + 1,tb_min,tb_max);
                h2[counter]->SetTitle((rightFlag(flags[i][j])).c_str());
                //for(int i = 0 ; i < tb.size() ; i++)
                //    h2[counter]->Fill(mhp[i],tb[i],value[i]);
                h2[counter]->SetMarkerStyle(kFullDotLarge);
                //h2[counter]->Draw("COLZ");
                h2[counter]->Write((rightFlag(flags[i][j])).c_str());
                counter++;
            }*/
        }
    }
    file<<"END_OF_FILE";
    file.close();
    //const int n_points=10;
    //double x_vals[n_points]={1,2,3,4,5,6,7,8,9,10};
    //double y_vals[n_points]={6,12,14,20,22,24,35,45,44,53};
    //double y_errs[n_points]={5,5,4.7,4.5,4.2,5.1,2.9,4.1,4.8,5.43};
    //TH2* h2 = new TH2F("X_Axis","Y_Axis",23,0,11,60,0,59);
    //for(int i = 0 ; i < n_points ; i++)
        //h2->Fill(x_vals[i],y_vals[i]);
    //TGraph graph(n_points,x_vals,y_vals);
    //h2->SetTitle("Measurement XYZ;lenght in cm;Arb Units");
    //h2->SetMarkerStyle(kFullDotLarge);
    //h2->Draw();
    //file.Close();
    return 0;
}
string nameGen(string path ,int index ,string type)
{
    string result;
    result += path;
    result += to_string(index);
    result += type;
    return result;
}
vector<string> getFlags(string fName)
{
    vector<string> flags;
    fName += "_flags.txt";
    fstream file;
    file.open(fName,ios::in);
    string line;
    while(getline (file, line))
        flags.push_back(line);
    return flags;
}
string findInFile(string path ,string flag ,string type , string Type)
{
    if(flag.find("-> SUSY") != string::npos)
        return findSUSYValue(path , Type);
    fstream file;
    file.open(path,ios::in);
    string line , result;
    while(getline (file, line))
    {
        bool b = false;
        string temp = "";
        for(int i = line.length() - 1 ; i >= 0 ; i--)
        {
            if(line[i] == ' ' && line[i-1] == '#')
                break;
            if(line[i] != ' ')
                b = true;
            if(b == true)
                temp = line[i] + temp;
        }
        if(flag.compare(temp) == 0)
        {
            if(type.compare("FH") == 0 && flag[0] == 'B' && flag[1] == 'R')
            {
                int flag = 0;
                for(int i = 0 ; i < line.length() ; i++)
                {
                    if(line[i] != ' ')
                        flag = 1;
                    else if(flag == 1)
                        break;
                    if(flag == 1)
                        result += line[i];
                }
            }
            else
            {
                for(int i = 0 ; i < line.size() ; i++)
                {
                    if(line[i] == '#')
                    {
                        for(int j = i - 4 ; line[j] != ' ' ; j--)
                            result = line[j] + result;
                        break;
                    }
                }
            }
            if(flag.compare("MHp") == 0)
                cout<<"("<<result<<" , ";
            if(flag.compare("TB") == 0)
                cout<<result<<")"<<endl;
            return result;
        }
    }
    string notFound = "0.00000000E+00";
    return notFound;
}
string findSUSYValue(string path , string type)
{
    fstream file;
    file.open(path,ios::in);
    string line , result;
    float bank = 0;
    string check;
    if(type.compare("FH_H1") == 0)
        check = "h0 ->";
    else if(type.compare("FH_H2") == 0)
        check = "HH ->";
    else if(type.compare("FH_H3") == 0)
        check = "A0 ->";
    else if(type.compare("FH_Hp") == 0)
        check = "Hp ->";
    else if(type.compare("FH_SM") == 0)
        check = "hSM ->";
    while(getline (file, line))
    {
        result = "";
        int flag = 0;
        if((line.find("Chargino") != string::npos || line.find("chargino") != string::npos || line.find("neutralino") != string::npos || line.find("Neutralino") != string::npos || line.find("Selectron") != string::npos || line.find("Smuon") != string::npos || line.find("S_nu") != string::npos) && line.find(check) != string::npos)
        {
            for(int i = 0 ; i < line.length() ; i++)
            {
                if(line[i] != ' ')
                    flag = 1;
                else if(flag == 1)
                    break;
                if(flag == 1)
                    result += line[i];
            }
            bank += strToFloat(result , 8);
        }
    }
    result = floatToStr(bank , -8);
    return result;
}
bool findSUSY(string path , string type)
{
    fstream file;
    file.open(path,ios::in);
    string line , result;
    float bank = 0;
    string check;
    if(type.compare("FH_H1") == 0)
        check = "h0 ->";
    else if(type.compare("FH_H2") == 0)
        check = "HH ->";
    else if(type.compare("FH_H3") == 0)
        check = "A0 ->";
    else if(type.compare("FH_Hp") == 0)
        check = "Hp ->";
    else if(type.compare("FH_SM") == 0)
        check = "hSM ->";
    while(getline (file, line))
    {
        
        if(line.find("Chargino") != string::npos || line.find("chargino") != string::npos || line.find("neutralino") != string::npos || line.find("Neutralino") != string::npos)
            if(line.find(check) != string::npos)
                return true;
    }
    return false;
}
bool isThere(string path ,string flag ,string Type)
{
    if(flag.find("-> SUSY") != string::npos)
        return findSUSY(path , Type);
    string line;
    fstream file;
    file.open(path,ios::in);
    while(getline (file, line))
    {
        if(line.find(flag) != string::npos)
            return true;
    }
    return false;
}
string findTB(string path ,string flag)
{
    string line , result = "";
    fstream file;
    file.open(path,ios::in);
    while(getline (file, line))
    {
        if(line.find(flag) != string::npos)
        {
            for(int i = 0 ; i < line.size() ; i++)
            {
                if(line[i] == '#')
                {
                    for(int j = i - 4 ; line[j] != ' ' ; j--)
                        result = line[j] + result;
                    break;
                }
            }
            break;
        }
    }
    return result;
}
string findMHp(string path ,string flag)
{
    string line , result;
    fstream file;
    file.open(path,ios::in);
    while(getline (file, line))
    {
        if(line.find(flag) != string::npos)
        {
            for(int i = 0 ; i < line.size() ; i++)
            {
                if(line[i] == '#')
                {
                    for(int j = i - 4 ; line[j] != ' ' ; j--)
                        result = line[j] + result;
                    break;
                }
            }
            break;
        }
    }
    return result;
}
float strToFloat(string base , int dp)
{
    char c[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    float result = 0 , p = 0;
    int dec = 1 , i = 0 , j , mul = 1 , mulp = 1;
    bool flag = false;
    if(base[0] == '-')
    {
        i = 1;
        mul = -1;
    }
    for(i ; base[i] != 'E' ; i++)
    {
        if(base[i] == '.')
            flag = true;
        else
        {
            int temp;
            for(int j = 0 ; j < 10 ; j++)
            {
                if(base[i] == c[j])
                    temp = j;
            }
            if(flag == false)
                result = result * 10 + temp;
            else
            {
                result = result + pow(10 , -1 * dec) * temp;
                dec ++;
            }
        }
    }
    if(base[i + 1] == '-')
    {
        mulp = -1;
    }
    j = i + 2;
    for(j ; j < base.length() ; j++)
    {
        int temp;
        for(int k = 0 ; k < 10 ; k++)
        {
            if(base[j] == c[k])
                temp = k;
        }
        p = p * 10 + temp;
    }
    p = p * mulp;
    p += dp;
    result = result * mul;
    return result * pow(10 , p);
}
string rightFlag(string flag)
{
    string result = "";
    int counter = 0;
    while(counter < flag.length())
    {
        if(flag[counter] == 'h' && flag[counter+1] == '0')
        {
            result += "H1";
            counter ++;
        }
        else if(flag[counter] == 'H' && flag[counter+1] == 'H')
        {
            result += "H2";
            counter ++;
        }
        else if(flag[counter] == 'A' && flag[counter+1] == '0')
        {
            result += "H3";
            counter ++;
        }
        else
            result += flag[counter];
        counter ++;
    }
    return result;
}
string floatToStr(float in , int dp)
{
    if(in == 0)
        return "0.00000000E+00";
    string result , temp;
    int power;
    temp = to_string(in);
    for(int i = 0 ; i < temp.length() ; i++)
    {
        if(temp[i] == '.')
        {
            if(i > 1)
            {
                power = i - 1;
            }
            else if(temp[i-1] != '0')
                power = 0;
            else
            {
                int counter = 1;
                for(int j = i + 1 ; j < temp.length() ; j++)
                {
                    if(temp[j] != '0')
                        break;
                    counter ++;
                }
                power = -1 * counter;
            }
        }
    }
    bool check = false , point = false;;
    for(int i = 0 ; i < temp.length() ; i++)
    {
        if(temp[i] == '.')
            continue;
        if(temp[i] != '0')
            check = true;
        if(check == true)
        {
            result += temp[i];
            if(point == false)
            {
                result += '.';
                point = true;
            }
        }
        if(result.length() == 10)
            break;
    }
    if(result.length() < 10)
    {
        for(int i = result.length() ; i < 10 ; i++)
        {
            result += "0";
        }
    }
    result += "E";
    power += dp;
    if(power < 0)
        result += "-";
    if(abs(power) < 10)
        result += "0";
    result += to_string(abs(power));
    return result;
}
int findNumberOfFiles(string path)
{
    int result = 0;
    DIR *d;
    struct dirent *dir;
    d = opendir(path.c_str());
    if (d)
    {
        while ((dir = readdir(d)) != NULL)
        {
            if(strcmp(dir -> d_name , ".") != 0  && strcmp(dir -> d_name , "..") != 0)
                result++;
        }
    }
    return result;
}


